package a

import (
	"encoding/json"
	"fmt"
	"reflect"

	"gorm.io/datatypes"
)

func A取map第一个key(m any) string {
	// 获取传入参数的反射值
	value := reflect.ValueOf(m)
	if value.Kind() != reflect.Map {
		return ""
	}
	// 获取map的迭代器
	iter := value.MapRange()
	// 检查map是否有元素
	if iter.Next() {
		// 获取第一个键的反射值
		key := iter.Key()
		// 检查键是否为字符串类型
		if key.Kind() == reflect.String {
			return key.String()
		}
	}
	return ""
}

func A反射调用(方法 any, 参数s ...any) (err error) {
	fnValue := reflect.ValueOf(方法)
	// 检查函数是否可调用
	if fnValue.Kind() == reflect.Func {
		// 创建输入参数切片,reflect.Value.Call是这样设计的，以求被调用函数入参可以随意数量和类型
		// input := []reflect.Value{reflect.ValueOf(参数s)}
		input := make([]reflect.Value, len(参数s))
		for i, param := range 参数s {
			input[i] = reflect.ValueOf(param)
		}
		// 调用函数
		results := fnValue.Call(input)
		// 获取返回的错误值
		if len(results) > 0 && !results[0].IsNil() {
			err, _ = results[0].Interface().(error)
			return err
		}
	}
	return
}

func A取字段值_数组(s any, 字段名 string) (字段值 []string) {
	字段反射值 := A取字段反射值(s, 字段名)
	if !字段反射值.IsValid() || 字段反射值.Len() == 0 {
		return nil
	}
	字段值断言, _ := 字段反射值.Interface().(datatypes.JSON)
	var 字段值any []any
	json.Unmarshal(字段值断言, &字段值any)
	// 将 字段值any 转换为字符串切片
	// 字段值 := make([]string, 0, len(字段值any))
	for _, item := range 字段值any {
		switch v := item.(type) {
		case float64:
			// 处理数字类型
			字段值 = append(字段值, fmt.Sprintf("%v", int(v)))
		case string:
			// 处理字符串类型
			字段值 = append(字段值, v)
		default:
			_ = fmt.Errorf("不支持的类型: %T", v)
		}
	}
	return
}

func A取反射el(s any) reflect.Value {
	var value reflect.Value
	// 判断 s 是否已经是 reflect.Value 类型
	if v, ok := s.(reflect.Value); ok {
		value = v
	} else {
		value = reflect.ValueOf(s)
	}
	// value := reflect.ValueOf(s)
	// 如果 value 所代表的值是一个指针，那么 value.Elem() 方法会返回指针所指向的实际值
	// if value.Kind() == reflect.Pointer {
	if value.Kind() == reflect.Ptr {
		value = value.Elem()
	}
	return value
}

// 获取反射值元素（处理指针情况）
// func A取反射值元素(value reflect.Value) reflect.Value {
// func A取反射el(value reflect.Value) reflect.Value {
// 	if value.Kind() == reflect.Ptr {
// 		return value.Elem()
// 	}
// 	return value
// }

// 获取反射值地址的接口表示
func A取反射值指针(value reflect.Value) any {
	if value.Kind() != reflect.Ptr {
		value = value.Addr()
	}
	// return value.Addr().Interface()
	return value.Interface()
}

func A成切片(实例 any) (res any) {
	modelType := reflect.TypeOf(实例)
	切片 := reflect.MakeSlice(reflect.SliceOf(modelType), 0, 0)
	res = 切片.Interface()
	return
}

func A成切片指针(实例 any) (res any) {
	modelType := reflect.TypeOf(实例)
	切片 := reflect.MakeSlice(reflect.SliceOf(modelType), 0, 0)
	// 获取切片的指针
	切片指针 := reflect.New(切片.Type())
	切片指针.Elem().Set(切片)
	// 将指针转换为 interface{} 类型返回
	res = 切片指针.Interface()
	return
}

func A成新实例指针(ptr any) any {
	value := reflect.ValueOf(ptr)
	if value.Kind() != reflect.Ptr {
		return fmt.Errorf("传入的参数必须是指针")
	}
	// 获取指针指向的实际值
	elem := value.Elem()
	// 创建一个新的同类型的实例
	newElem := reflect.New(elem.Type())
	// 返回新的实例指针
	return newElem.Interface()
}

func A成新实例指针切片(ptr any) any {
	value := reflect.ValueOf(ptr)
	if value.Kind() != reflect.Ptr {
		return fmt.Errorf("传入的参数必须是指针")
	}
	// 获取指针指向的实际值
	elem := value.Elem()
	// 创建一个新的同类型的实例
	newElem := reflect.New(elem.Type())

	// 将新的实例指针放入切片
	result := make([]any, 1)
	result[0] = newElem.Interface()

	return result
}

// func A实例赋默认值(实例 any) any {
// 	value := reflect.ValueOf(实例)
// 	if value.Kind() == reflect.Struct {
// 		modelType := reflect.TypeOf(实例)
// 		// 会创建一个 modelType 类型的新值，并返回一个指向该值的 reflect.Value 类型的指针
// 		ptr := reflect.New(modelType)
// 		// 将原始对象的值设置到新创建的指针指向的对象中
// 		ptr.Elem().Set(value)
// 		//  Interface() 方法，将这个 reflect.Value 转换为 interface{} 类型。由于原始的 reflect.Value 是一个指针，所以最终返回的 interface{} 类型的值实际上是一个指向 modelType 类型的指针。
// 		return ptr.Interface()
// 	}
// 	return nil
// }

func A实例转指针(s any) any {
	value := reflect.ValueOf(s)
	if value.Kind() == reflect.Pointer {
		return s
	}
	if value.Kind() == reflect.Struct {
		modelType := reflect.TypeOf(s)
		// 会创建一个 modelType 类型的新值，并返回一个指向该值的 reflect.Value 类型的指针
		ptr := reflect.New(modelType)
		// 将原始对象的值设置到新创建的指针指向的对象中
		ptr.Elem().Set(value)
		//  Interface() 方法，将这个 reflect.Value 转换为 interface{} 类型。由于原始的 reflect.Value 是一个指针，所以最终返回的 interface{} 类型的值实际上是一个指向 modelType 类型的指针。
		return ptr.Interface()
	}
	return nil
}

func A取字段反射值(s any, 字段名 string) (字段反射值 reflect.Value) {
	value := A取反射el(s)
	字段反射值 = value.FieldByName(字段名)
	return
}

func A予id值(s any, 字段值 uint) bool {
	field := A取字段反射值(s, "ID")
	// 将传入的值转换为反射值
	reflectValue := reflect.ValueOf(字段值)
	// 检查类型是否匹配
	if !reflectValue.Type().AssignableTo(field.Type()) {
		return false
	}
	// 赋值操作
	field.Set(reflectValue)
	return true
}

func A予字段值_datatypes点json(s any, 字段名 string, 字段值 any) bool {
	jsonData, _ := json.Marshal(字段值)
	jsonValue := datatypes.JSON(jsonData)
	return A予字段值(s, 字段名, jsonValue)
}

func A予字段值(s any, 字段名 string, 字段值 any) bool {
	field := A取字段反射值(s, 字段名)
	// 将传入的值转换为反射值
	reflectValue := reflect.ValueOf(字段值)
	// 检查类型是否匹配
	if !reflectValue.Type().AssignableTo(field.Type()) {
		return false
	}
	// 赋值操作
	field.Set(reflectValue)
	return true
}

func A有字段否(s any, 字段名 string) bool {
	value := A取反射el(s)
	field := value.FieldByName(字段名)
	res := field.IsValid()
	return res
}

func A有方法否(s any, 方法名 string) bool {
	方法 := A取方法(s, 方法名)
	return 方法.IsValid()
}

func A取方法(s any, 方法名 string) (方法 reflect.Value) {
	value := A取反射el(s)
	// 如果 方法定义在结构体 指针上，需要将其转换为指针类型
	if value.Kind() != reflect.Ptr {
		value = value.Addr()
	}
	方法 = value.MethodByName(方法名)
	return 方法
}

func A取字段值(s any, 字段名 string) (字段值 any) {
	var value reflect.Value
	// 判断 s 是否已经是 reflect.Value 类型
	if v, ok := s.(reflect.Value); ok {
		value = v
	} else {
		value = reflect.ValueOf(s)
	}
	// value := reflect.ValueOf(s)
	// 如果 value 所代表的值是一个指针，那么 value.Elem() 方法会返回指针所指向的实际值
	if value.Kind() == reflect.Pointer {
		value = value.Elem()
	}
	modelType := value.Type()
	// fmt.Printf("modelType 👉 %+v\n", modelType)
	_, ok := modelType.FieldByName(字段名)
	if !ok {
		// fmt.Errorf("传入的结构体类型 %s 中不存在名为 %s 的字段", s, 字段名)
		字段值 = nil
	} else {
		字段值 = value.FieldByName(字段名).Interface()
	}
	return
}

func A取id(s any) (字段值 uint) {
	字段值 = A取字段值(s, "ID").(uint)
	return
}

func A取状态(s any) (字段值 string) {
	字段值 = A取字段值(s, "A状态").(string)
	return
}

func A取字符串字段值(s any, 字段名 string) (字段值 string) {
	字段值 = A取字段值(s, 字段名).(string)
	return
}

func A取uint字段值(s any, 字段名 string) (字段值 uint) {
	字段值 = A取字段值(s, 字段名).(uint)
	return
}

// func A取page(s any) (m map[string]any) {
// 	m = make(map[string]any)
// 	字段名 := "PageSize"
// 	m[字段名] = A取字段值(s, 字段名).(int)

// 	字段名 = "Page"
// 	m[字段名] = A取字段值(s, 字段名).(int)

// 	字段名 = "Order"
// 	m[字段名] = A取字段值(s, 字段名).(string)

// 	return
// }
